<template>
  <div>
    <el-table
      v-if="isShow"
      v-loading="loading"
      lazy
      :key="symbolKey"
      :data="categoryList"
      border
      style="width: 100%; margin-bottom: 20px"
      :row-key="rowKey"
      :load="load"
      :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
      :row-class-name="getRowClassName"
    >
      <el-table-column prop="id" label="分类ID" width="180"> </el-table-column>
      <el-table-column prop="name" label="分类名称" sortable> </el-table-column>
      <el-table-column label="操作">
        <template slot="header" align="center" slot-scope="scope">
          <el-input
            v-model="search"
            size="mini"
            placeholder="按Enter键添加一级分类"
            @keyup.enter.native="addCategory({ level: 0, name: search })"
          />
        </template>
        <template #default="{ row }">
          <HintButton
            v-show="row.level !== 3"
            title="添加"
            type="success"
            size="mini"
            icon="el-icon-plus"
            @click="addCategory(row)"
          />
          <HintButton
            title="修改"
            type="warning"
            size="mini"
            icon="el-icon-edit"
            @click="updateCategory(row)"
          />
          <HintButton
            title="删除"
            type="primary"
            size="mini"
            icon="el-icon-delete"
            @click="deleteCategory(row)"
          />
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>
<script>
export default {
  name: "Category",
  data() {
    return {
      categoryList: [],
      isShow: false,
      search: "",
      symbolKey: "", // 不同的key
      loading: true,
    };
  },
  mounted() {
    this.categoryList1();
  },
  methods: {
    /**
     * @description: 获取一级分类,判断有没有子节点
     */
    async categoryList1() {
      try {
        const result = await this.$API.category.getCategoryList1();
        result.data.forEach(async (item, index, array) => {
          item.level = 1;
          const result = await this.$API.category.getCategoryList2(item.id);
          if (result.data.length > 0) {
            item.hasChildren = true;
          } else {
            item.hasChildren = false;
          }
          // 判断最后一次循环
          if (array.length - 1 === index) {
            this.loading = false;
            this.isShow = true;
          }
        });
        this.categoryList = result.data;
      } catch (error) {
        this.$Message.error(error?.message ?? "获取一级分类列表失败");
      }
    },
    /**
     * @description: 懒加载节点
     */
    async load(tree, treeNode, resolve) {
      if (tree.level === 1) {
        try {
          const result = await this.categoryList2(tree.id);
          resolve(result);
        } catch (error) {
          this.$message.error(error?.message ?? "获取二级分类列表失败");
        }
      } else if (tree.level === 2) {
        try {
          const result = await this.categoryList3(tree.id);
          resolve(result);
        } catch (error) {
          this.$message.error(error?.message ?? "获取三级分类列表失败");
        }
      }
    },
    /**
     * @description: 获取二级分类,判断有没有子节点
     */
    async categoryList2(id) {
      const result = await this.$API.category.getCategoryList2(id);
      let arr = [];
      const p = await Promise.allSettled(
        result.data.map(async (item) => {
          item.level = 2;
          const result = await this.$API.category.getCategoryList3(item.id);
          if (result.data.length > 0) {
            item.hasChildren = true;
          } else {
            item.hasChildren = false;
          }
          return item;
        })
      );
      p.forEach((item) => {
        if (item.status === "fulfilled") {
          arr.push(item.value);
        }
      });
      return arr;
    },
    /**
     * @description: 获取三级分类
     */
    async categoryList3(id) {
      const result = await this.$API.category.getCategoryList3(id);
      result.data.forEach((item) => {
        item.level = 3;
      });
      return result.data;
    },
    rowKey(row) {
      return row.level + "-" + row.id + "-" + row.name;
    },
    /**
     * @description: 添加一级或二级或三级分类
     */
    addCategory(row) {
      const { level, id, name } = row;
      const title =
        level === 0
          ? "添加一级分类"
          : level === 1
          ? "添加二级分类"
          : "添加三级分类";
      if (level === 0) {
        this.$confirm(`确认添加一级分类名字：${name}`, title, {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning",
        })
          .then(async () => {
            try {
              await this.$API.category.saveCategory1OrCategory2OrCategory3({
                name,
                level: level + 1,
                id,
              });
              this.$message.success("添加一级分类成功");
              this.isShow = false;
              this.loading = true;
              this.categoryList1();
            } catch (error) {
              this.$message.error(error?.message ?? "添加一级分类失败");
            }
          })
          .catch(() => {
            this.$message({
              type: "info",
              message: "取消添加一级分类",
            });
          });
      } else {
        this.$prompt(`请输入${level === 1 ? "二级" : "三级"}分类名字`, title, {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          inputPattern: /^[a-zA-Z0-9、\u4e00-\u9fa5]{2,20}$/,
          inputErrorMessage: "请输入2-20位中文、数字、字母、顿号",
        })
          .then(async ({ value }) => {
            try {
              await this.$API.category.saveCategory1OrCategory2OrCategory3({
                name: value,
                level: level + 1,
                id,
              });
              this.$message.success(
                `添加${level === 1 ? "二级" : "三级"}分类成功`
              );
              this.changeSymbolKey();
              if (level === 1) {
                this.categoryList.find(
                  (item) => item.id === id
                ).hasChildren = true;
              }
            } catch (error) {
              this.$message.error(
                `添加${level === 1 ? "二级" : "三级"}分类失败`
              );
            }
          })
          .catch(() => {
            this.$message({
              type: "info",
              message: `取消添加${level === 1 ? "二级" : "三级"}分类`,
            });
          });
      }
    },
    /**
     * @description: 修改一级或二级或三级分类
     */
    updateCategory(row) {
      const { level, id, name } = row;
      const title =
        level === 1
          ? "修改一级分类"
          : level === 2
          ? "修改二级分类"
          : "修改三级分类";
      this.$prompt(
        `请输入${level === 1 ? "一级" : level === 2 ? "二级" : "三级"}分类名字`,
        title,
        {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          inputPattern: /^[a-zA-Z0-9、\u4e00-\u9fa5]{2,20}$/,
          inputErrorMessage: "请输入2-20位中文、数字、字母、顿号",
          inputValue: name,
        }
      )
        .then(async ({ value }) => {
          try {
            await this.$API.category.updateCategory1OrCategory2OrCategory3({
              name: value,
              level,
              id,
            });
            this.$message.success(
              `更新${
                level === 1 ? "一级" : level === 2 ? "二级" : "三级"
              }分类成功`
            );
            if (level === 1) {
              this.isShow = false;
              this.categoryList1();
            } else {
              this.changeSymbolKey();
            }
          } catch (error) {
            this.$message.error(
              error?.message ??
                `修改${
                  level === 1 ? "一级" : level === 2 ? "二级" : "三级"
                }分类失败`
            );
          }
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: `取消更新${
              level === 1 ? "一级" : level === 2 ? "二级" : "三级"
            }分类`,
          });
        });
    },
    /**
     * @description: 删除一级或二级或三级分类
     */
    deleteCategory(row) {
      const { level, id, name } = row;
      const title =
        level === 1
          ? "删除一级分类"
          : level === 2
          ? "删除二级分类"
          : "删除三级分类";
      this.$confirm(`确认删除：${name}`, title, {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(async () => {
          try {
            await this.$API.category.deleteCategory1OrCategory2OrCategory3({
              level,
              id,
            });
            this.$message.success(
              `删除${
                level === 1 ? "一级" : level === 2 ? "二级" : "三级"
              }分类成功`
            );
            if (level === 1) {
              const index = this.categoryList.findIndex(
                (item) => item.id === id
              );
              this.categoryList.splice(index, 1);
            } else {
              this.changeSymbolKey();
            }
          } catch (error) {
            this.$message.error(
              error?.message ??
                `删除${
                  level === 1 ? "一级" : level === 2 ? "二级" : "三级"
                }分类失败`
            );
          }
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: `取消删除${
              level === 1 ? "一级" : level === 2 ? "二级" : "三级"
            }分类`,
          });
        });
    },
    changeSymbolKey() {
      this.loading = true;
      this.symbolKey = Symbol(new Date().toString());
      this.loading = false;
    },
    getRowClassName({ row }) {
      if (row.level === 1) {
        return "category-level-1";
      } else if (row.level === 2) {
        return "category-level-2";
      } else {
        return "category-level-3";
      }
    },
  },
};
</script>
<style>
.el-table .level2-row {
  background: #f0f9eb;
}
</style>